﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Web.Mvc;
using Xenta.Attributes;
using Xenta.Utils;
using Xenta.Web.Controllers;

namespace Xenta.Web.Areas.Wizard.Controllers
{
    [Authenticate]
    public sealed class ShoppingCartController : ExtController
    {
        #region GET/POST Actions

        [HttpGet, RestoreState]
        public ActionResult Show()
        {
            dynamic m = new ExpandoObject();
            m.Carts = Svc.ProcessOperation("SearchShoppingCarts", new
            {
                CustomerID = JDM.Int32(Svc.Customer.EntityID)
            }, new
            {
                DisclosureLevel = "Entire"
            });
            m.Options = Svc.ProcessOperation("SearchSalesOptions", new
            {
                LanguageID = JDM.Int32(Svc.Localization.Language.EntityID),
                FlagMask = "Active,Order,Common"
            }, new
            {
                DisclosureLevel = "Entire"
            });
            return View(m);
        }

        [HttpGet, PersistState]
        public ActionResult Put(int salesItemID, 
            string price, 
            string quantity,
            string options = "")
        {
            return Put(salesItemID, 
                price,
                quantity, 
                !String.IsNullOrWhiteSpace(options) 
                    ? options.Split(',')
                        .Select(x => x.ParseAs<Int32>())
                        .ToArray() 
                    : null);
        }

        [HttpPost, PersistState]
        public ActionResult Put(int salesItemID, 
            string price, 
            string quantity, 
            int[] options = null)
        {
            var i = Svc.ProcessOperation("GetSalesItem", new
            {
                EntityID = salesItemID
            }, new
            {
                DisclosureLevel = "Entire",
                DisclosureOptions = new Dictionary<String, String>
                {
                    { "TranslatedTo", JDM.String(Svc.Localization.Language.Code) }
                }.Unload()
            });
            if(i == null)
                return HttpNotFound();
            if(options == null)
            {
                options = (i.Options as IEnumerable<dynamic>)
                    .Where(x => JDM.HasFlags(x.Flags, "DefaultChoice"))
                    .Select(x => (int)JDM.Int32(x.EntityID))
                    .ToArray();
            }
            var c = TakeCart(JDM.Int32(i.Seller.EntityID), "Keys");
            try
            {
                Svc.ProcessOperation("PutItemToShoppingCart", new
                {
                    CartID = JDM.Int32(c.EntityID),
                    SalesItemID = salesItemID,
                    Quantity = Svc.Numeric(quantity),
                    Price = Svc.Price(price),
                    OptionIDs = options
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Show").Ctrl("Item").Area("Store").Set(new
            {
                id = salesItemID
            }).Localized());
        }

        [HttpGet, PersistState]
        public ActionResult Remove(int cartItemID, string quantity)
        {
            try
            {
                Svc.ProcessOperation("RemoveItemFromShoppingCart", new
                {
                    CartItemID = cartItemID,
                    Quantity = StringHelper.ParseAs<Decimal>(quantity)
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Show").Localized());
        }

        [HttpGet, PersistState]
        public ActionResult Clear(int id)
        {
            try
            {
                Svc.ProcessOperation("ClearShoppingCart", new
                {
                    EntityID = id
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Show").Localized());
        }

        [HttpGet, RestoreState]
        public ActionResult Checkout(int id,
            int? billingAddressID,
            int? shippingAddressID,
            int? sellerAddressID)
        {
            dynamic m = new ExpandoObject();

            m.Cart = Svc.ProcessOperation("GetShoppingCart", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Entire"
            });
            if(m.Cart == null)
                return HttpNotFound();

            var items = m.Cart.Items as IEnumerable<dynamic>;
            if(!items.Any())
                return HttpNotFound();

            m.Seller = Svc.ProcessOperation("GetSeller", new
            {
                EntityID = JDM.Int32(items.Select(x => x.SalesItem.Seller).First().EntityID)
            }, new
            {
                DisclosureLevel = "Entire"
            });
            m.Customer = Svc.ProcessOperation("GetCustomer", new
            {
                EntityID = JDM.Int32(Svc.Customer.EntityID)
            }, new
            {
                DisclosureLevel = "Entire"
            });
            m.ShippingOptions = Enumerable.Empty<dynamic>();
            m.SalesModels = Enumerable.Empty<dynamic>();

            if(billingAddressID.HasValue &&
                shippingAddressID.HasValue &&
                sellerAddressID.HasValue)
            {
                m.ShippingOptions = Svc.ProcessOperation("GetAvailableShippingOptions", new
                {
                    ShippingAddressID = JDM.Int32(shippingAddressID.Value),
                    SellerAddressID = JDM.Int32(sellerAddressID.Value),
                });
                m.SalesModels = Svc.ProcessOperation("GetAvailableSalesModels", new
                {
                    CartID = id
                });
            }

            return View(m);
        }

        [PersistState]
        public ActionResult MapOption(int cartID, string options)
        {
            if(!String.IsNullOrWhiteSpace(options))
            {
                try
                {
                    foreach(var i in options.Split(',').Select(x => x.ParseAs<Int32>()))
                    {
                        Svc.ProcessOperation("MapSalesOptionToShoppingCart", new
                        {
                            EntityID = cartID,
                            ChildID = i
                        });
                    }
                }
                catch(Exception ex)
                {
                    ModelState.AddModelError("API", ex);
                }
            }
            return RedirectToAction(Loc.Act("Show").Localized());
        }

        [PersistState]
        public ActionResult UnmapOption(int cartID, int optionID)
        {
            try
            {
                Svc.ProcessOperation("UnmapSalesOptionFromShoppingCart", new
                {
                    EntityID = cartID,
                    ChildID = optionID
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Show").Localized());
        }

        #endregion

        #region Child Actions

        [ChildActionOnly]
        public ActionResult _Overview()
        {
            var m = Svc.ProcessOperation("SearchShoppingCarts", new
            {
                CustomerID = JDM.Int32(Svc.Customer.EntityID)
            }, new
            {
                DisclosureLevel = "Entire"
            });
            return View(m);
        }

        #endregion

        #region Utils

        private dynamic TakeCart(int sellerID, string disclosure = "Entire")
        {
            dynamic m = null;
            string attrKey = Par.In("WebPortal").Of("Store").Group("Cart").Name(sellerID);
            int cartID = Svc.Attribute(attrKey, 0);
            if(cartID != 0)
            {
                m = Svc.ProcessOperation("GetShoppingCart", new
                {
                    EntityID = cartID
                }, new
                {
                    DisclosureLevel = disclosure
                });
            }
            if(m == null)
            {
                m = Svc.ProcessOperation("CreateShoppingCart", new
                {
                    CustomerID = JDM.Int32(Svc.Customer.EntityID)
                }, new
                {
                    DisclosureLevel = disclosure
                });
                Svc.ProcessOperation("SetAccountAttribute", new
                {
                    HolderID = JDM.Int32(Svc.Account.EntityID),
                    Key = attrKey,
                    Value = JDM.Int32(m.EntityID)
                });
            }
            return m;
        }

        #endregion
    }
}
